import { eachStyleProperty } from './each_property';
import { changeProperty } from './change_property';

const tried = {};
export function isAllFailed(): boolean {
  const status = Object.values(tried);
  if (!status.length) return false;
  return status.every((v: number) => v === 11);
}
export function isAllSuccessed(): boolean {
  return Object.values(tried).every((v: number) => v === 10);
}
export function isAllFinished(): boolean {
  console.log('debug isAllFinished', JSON.parse(JSON.stringify(tried)));
  return Object.values(tried).every((v: number) => v >= 10);
}

const timeoutValue = 3000;
const timer = {};
function cancelTimer(href: string) {
  if (timer[href]) {
    clearTimeout(timer[href]);
    timer[href] = null;
  }
}

function retrySuccessed(href: string, programId: string) {
  console.log('debug retrySuccessed by', programId, 'which href=', href);

  cancelTimer(href);

  tried[href] = 10;

  eachStyleProperty(false, changeProperty);
}

function retryFailed(href: string) {
  console.log('debug retryFailed at last which href=', href);

  cancelTimer(href);

  tried[href] = 11;
}

function retryByCrossOrigin(href: string) {
  cancelTimer(href);

  const link = document.createElement('link');
  link.setAttribute('crossorigin', 'crossorigin');
  link.setAttribute('rel', 'stylesheet');
  link.setAttribute('type', 'text/css');
  link.setAttribute('href', href);

  const programId = 'CrossOriginRerequest';
  link.onload = retrySuccessed.bind(null, href, programId);
  link.onerror = retryProxy.bind(null, href, programId);
  timer[href] = setTimeout(retryProxy, timeoutValue, href, programId);

  setTimeout((node) => document.head.appendChild(node), 0, link);
}

type fallbackProgram = (href: string) => void;
const fallbacks: fallbackProgram[] = [
  (_: string) => {},
  retryByCrossOrigin,
  retryFailed,
];
function retryProxy(href: string, programId: string) {
  // console.log('debug retryProxy from', programId, 'which href=', href);

  cancelTimer(href);

  const program = fallbacks[tried[href]++];
  if (program) {
    program(href);
  }
}

/*
 * 矛盾：
 * 有的网站，CSS脚本必须是跨域请求时，才能取到里面的样式规则进行转换；（CSND博客页）
 * 又有一些网站，CSS脚本不能被跨域请求，却不能在模式一下切换成功，判定retryAllFailed后落入模式二；（Gitee.com）
 * 但是偏偏有些网站，CSS脚本不能被跨域请求，却能在模式一下切换成功，判定retryAllFailed后落入模式二反而多余；（baidu.com）
 *
 * 解决：
 * 还好，在正确实现simple wait后，baidu带来的回旋式720度大bug解决了
 */
export function retryStyleSheet(styleSheet: CSSStyleSheet) {
  // console.log('debug retryStyleSheet need retrying', styleSheet.href);

  const href = styleSheet.href;
  const ownerNode = styleSheet.ownerNode;
  if (!href || tried[href] || ownerNode?.nodeType !== Node.ELEMENT_NODE) {
    return;
  }
  tried[href] = 1;

  const programId = 'simple-wait';
  const ownerElement = ownerNode as HTMLElement;
  ownerElement.onload = retrySuccessed.bind(null, href, programId);
  ownerElement.onerror = retryProxy.bind(null, href, programId);
  timer[href] = setTimeout(retryProxy, timeoutValue, href, programId);

  console.log('debug retryStyleSheet now retrying', styleSheet.href);
}
